
#include <stdlib.h>
#include <string.h>
/**/

#include "BSP_Delay.h"
#include "BSP_Sleep.h"
#include "BSP_RS485.h"

/* Scheduler include files. */
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#include "timers.h"
#include "stream_buffer.h"
/**/
#include "Buzzer.h"
#include "Light.h"
#include "WG.h"
#include "WatchDog.h"

/**/
#include "Contract.h"
#include "util.h"
#include "fun_time.h"
/**/
#include "Timer.h"
#include "BSP.h"
#include "Bit.h"
#include "Driver.h"
#include "Env.h"
#include "Init.h"
#include "SoftCrc.h"
#include "USB_HID.h"
#include "IDCard/ID_Process.h"
#include "DeviceLight.h"
#include "OutPut.h"
#include "Reader.h"
#include "Command.h"
#include "HIDKeyboard.h"
#include "SignalService.h"
#include "RealTimeClock.h"
#include "ReaderQr.h"
#include "ReaderBLE.h"

#include "Controller/controller.h"
/*---------------------------------------------------------------------------------------*/
#include "usbd_std.h"

#include "Debug.h"

/*-----------------------------------------------------------------------------------------*/
extern volatile uint8_t rebootFlag;

CSN_T CSN;

SemaphoreHandle_t mainSemaphore;

static TimerHandle_t tickTimer;
static uint32_t tickCount;
static volatile uint8_t readerReady;
static uint8_t readCount;
static uint8_t cfgWg;
static uint16_t rtcCount;

/* The task that is created three times. */
static void MainTask(void *param);
void ReadModeApply(void);

/*-----------------------------------------------------------*/

void Main_NotifyFromISR(uint8_t* msg){
	static BaseType_t xHigherPriorityTaskWoken;
	xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(mainSemaphore, &xHigherPriorityTaskWoken);
	if(xHigherPriorityTaskWoken){
		taskYIELD ();
	}
}

static void tickTimerCallback(void *param) {
  // 50ms
  ++tickCount;
  readerReady = 1;
  if(rtcCount > 0){
	rtcCount--;
  }
}

void Main_StartTask(void) {
  mainSemaphore = xSemaphoreCreateBinary();

  tickTimer =
      xTimerCreate(/* Just a text name, not used by the RTOS kernel. */
                   "tickTimer",
                   /* The timer period in ticks, must be greater than 0. */
                   pdMS_TO_TICKS(100),
                   /* The timers will auto-reload themselves when they
                   expire. */
                   pdTRUE,
                   /* The ID is used to store a count of the number of
                   times the timer has expired, which is initialized to 0. */
                   (void *)0,
                   /* Each timer calls the same callback when it expires. */
                   tickTimerCallback);
  xTimerStart(tickTimer, 100);
  if (pdPASS != xTaskCreate(MainTask, (const char *)"Main", 512, NULL, 2,
                            (xTaskHandle *)NULL)) {
    ASSERT(0);
  }
}


static int ReadConfigCard(void) {
  int ret;
  int i;
  for (i = 0; i < 6; i++) {
	DeviceLight_Flash(1, Color_Green, 820);
	Buzzer_AsyncBeep(820);
    ret = Reader_ConfigService();
    if (!ret) {
      break;
    }
    BSP_Sleep_Ms(790);
    ret = Reader_ConfigService();
    if (!ret) {
      break;
    }
    BSP_Sleep_Ms(790);
  }
  return ret;
}

void StartUp(void) {
  Reader_Init();
  Reader_BLE_Init();
#ifndef DEBUG
  int ret = ReadConfigCard();

  if (!ret) {
	DeviceLight_Flash(1, Color_Green, 2000);
    Buzzer_Beep(2000);
  }
#else
  DeviceLight_Flash(1, Color_Green, 400);
  Buzzer_Beep(400);
#endif 

  readerReady = 0;
  ReadModeApply();
  Command_Init();
  controller_init();
}

static void Reader_Warnning(uint8_t count) {
	DeviceLight_Flash(count, Color_Red, 100);
	Buzzer_AsyncBeepMult(count, 100, 100);
}

static void Reader_Error(int ret) {
  if (!envData.rdErrorWarnning) {
    return;
  }

  if (ret == -100) {
    Reader_Warnning(3);
  } else if (ret == -101) {
    Reader_Warnning(4);
  }
}

static void BellReport(void){
	static uint32_t bellNum = 999999;
	uint8_t rBuf[4];
	memset(rBuf, 0, sizeof(rBuf));
	if(envData.wgReverse){
		memcpy(rBuf, &bellNum, sizeof(bellNum));
	}
	else{
		Mem_Reverse_Copy(rBuf, (uint8_t*)&bellNum, sizeof(bellNum));
	}
	OutPut_Out(0, rBuf, 4);
	Command_CharSendFrame(1, 0xAA, envData.devAddr, 200, (uint8_t*)&bellNum, sizeof(bellNum));
}

static void KeyboardTask(void){
	uint8_t kval;
	
	if(KeyBoard_Scan(&kval)){
		Buzzer_AsyncBeep(100);
		if(kval < 0x0C){
#if 0
			OutPut_Key(kval);
			Command_Rs485OutKey(kval);
#endif 
		  	input_event_t e;
		  	controller_input_event(input_event_build(&e, EV_T_Key, &kval, 1));
		}
		else{
			BellReport();
		}
	}
}


static void TampReport(void){
	static uint32_t tampSN = 9999999;
	static uint32_t tampCount;

	if(++tampCount > 600){
		tampCount = 0;
		uint8_t rBuf[4];
		memset(rBuf, 0, sizeof(rBuf));
		if(envData.wgReverse){
			memcpy(rBuf, &tampSN, sizeof(tampSN));
		}
		else{
			Mem_Reverse_Copy(rBuf, (uint8_t*)&tampSN, sizeof(tampSN));
		}
		OutPut_Out(0, rBuf, 4);
		Command_CharSendFrame(1, 0xAA, envData.devAddr, 200, (uint8_t*)&tampSN, sizeof(tampSN));
	}
}


static void SoftRTC_Sync(void){
	struct tm_s tim;

	RealTimeClock_Get(&tim);
	uint32_t sec = fun_mktime(&tim);
	BSP_Timer_SetSec(sec);
}
void Test(void);
void CH455_Test( void );
int Reader_Qr_ReadCardNo(char* qr, uint32_t* no);
void CardWG_GetData(uint8_t reverse, uint8_t rightAlign, uint8_t wg, 
	uint8_t* ibuf, uint8_t ilen, uint8_t* obuf, uint8_t* olen){
/*
WG输出数据：
	1.卡号：
	1）反序输出：
		CPU卡和MF卡卡号输出标准：
		            WG34：4，3，2，1
		             WG26：3，2，1
		             WG66：0，0，0，0，4，3，2，1
		身份证卡号输出标准：
		             WG26：7，6，5
		              WG34：8，7，6，5
		              WG66：8，7，6，5，4，3，2，1 
		7字节卡卡号输出标准：
		              WG26：6，5，4
		              WG34：7，6，5，4
		              WG66:  7，6，5，4，3，2，1，88

	2）正序输出：
		CPU卡和MF卡卡号输出标准：
					WG34输出为1,2,3,4
					 WG26输出为2,3,4
					 WG66输出为00 00 00 00， 1,2,3,4
		身份证卡号输出标准：
					 WG26：6,7,8
					  WG34：5,6,7,8
					  WG66：1,2,3,4,5,6,7,8
		7字节卡卡号输出标准：
					  WG26：6,7,8
					  WG34：4,5,6,7
					  WG66:  88,1,2,3,4,5,6,7
	2.内容：
	1）反序输出：
		WG34：4，3，2，1
		WG26：4，3，2
		WG66：4，3，2，1，0，0，0，0
	2）正序输出：
		WG34：1，2，3，4
		WG26：2，3，4
		WG66：0，0，0，0，1，2，3，4
*/	
	uint8_t nByte = wg / 8;
	uint8_t *tail = ibuf + ilen;
	uint8_t len;
	
	if(!rightAlign && ilen >= 4 && nByte < 4){
		len = 4;
		memcpy(obuf, tail - len, len);
	}
	else{
		len = nByte < ilen ? nByte : ilen;
		memcpy(obuf, tail - len, len);
	}
	if(!reverse){
		Mem_Reverse(obuf, len);
	}
	*olen = nByte;
}

static void QrHidKeyboard_Report(uint8_t buf[], uint32_t len){
	uint8_t mode = envData.qrWorkMode;
	uint8_t lsb;
	uint8_t rep_mode;
	if(mode == ENV_Qr_WorkMode_HNEncrypt){
		uint8_t tbuf[8];
		uint8_t tlen = 0;
		
		memset(tbuf, 0, sizeof(tbuf));
		CardWG_GetData(envData.qrReverse, 0, envData.wg, buf, len, tbuf, &tlen);
		rep_mode = REP_FRM_DEC;
		lsb = 0;
		HIDKeyboard_Report(lsb, rep_mode, buf, len);
		return;
	}
	else
	if(mode == ENV_Qr_WorkMode_ZKEncrypt){
		rep_mode = REP_FRM_DEC;
		lsb = 1;
	}
	else{
		rep_mode =  REP_FRM_RAW;
		lsb = 0;
	}
	HIDKeyboard_Report(lsb, rep_mode, buf, len);
}

//韦根数据明文10进制数字，最多输出18位。
//
static void QrWG_SendDataString(uint8_t wg, uint8_t buf[], uint32_t len){
	uint64_t val;

	if(len == 0 || DecCharToValue(buf[0]) > 9){
		return;
	}
	
	if(len > 18){
		len = 18;
	}
	
	DecStrToValue(buf, len, &val);
	WG_Send((uint8_t*)&val, wg - 2, 1);
}

//输出带有门权限数据
static void QrWG_OutWithDid(uint8_t wg, uint8_t* buf, uint32_t len){
	uint8_t tbuf[16];
	uint8_t tlen;	
	uint8_t uid[4];
	uint8_t ulen = 0;
	
	memset(uid, 0, sizeof(uid));
	Mem_Reverse_Copy(tbuf, buf, 4);
	CardWG_GetData(envData.qrReverse, 0, 32, tbuf, 4, uid, &ulen);
	memcpy(tbuf, uid, ulen);
	memcpy(tbuf + ulen, buf + 4, len - 4);
	tlen = ulen + len - 4;
	//自适应韦根输出
	WG_Send(tbuf, tlen * 8, 1);
}

static void QrWG_OutUid(uint8_t wg, uint8_t* buf, uint32_t len){
	uint8_t tbuf[8];
	uint8_t tlen = 0;
	uint8_t uid[4];
	
	memset(tbuf, 0, sizeof(tbuf));	
	if(len == 8)
		Mem_Reverse_Copy(uid, buf + 4, 4);
	else
		Mem_Reverse_Copy(uid, buf, 4);
	CardWG_GetData(envData.qrReverse, 0, wg, uid, 4, tbuf, &tlen);
	WG_Send(tbuf, tlen * 8, 1);
}

static void QrWG_Send(uint8_t buf[], uint32_t len){
	uint8_t wg = envData.wg;
	uint8_t mode = envData.qrWorkMode;
	
	if(mode == ENV_Qr_WorkMode_HNEncrypt){
		//华诺加密模式
		uint64_t val;
		
		if(len == 0 || DecCharToValue(buf[0]) > 9){
			return;
		}
		
		if(len > 18){
			len = 18;
		}
		
		DecStrToValue(buf, len, &val);
		if(envData.qrDidOut){
			QrWG_OutWithDid(wg, (uint8_t*)&val, len);
		}
		else{
			QrWG_OutUid(wg, (uint8_t*)&val, 4);
		}
	}
	else
	if(mode == ENV_Qr_WorkMode_ZKEncrypt){
		WG_Send(buf, wg - 2, 1);
	}
	else{
		QrWG_SendDataString(wg, buf, len);
	}
}
#if 0
static void  HNQR_Change(void){
	uint64_t val;
	const uint8_t valTmp = 10;
	uint32_t tmp = 1; 
	uint8_t valArr[20];
	uint8_t valArrLen = 0;
	uint8_t i = 0;
	int tmpPow = 10;
	HNQrRecord_T* qrRecord = (HNQrRecord_T*)qrBuffer;
	memcpy((uint8_t *)&val , (uint8_t *)qrRecord, 8 );
	Mem_Reverse((uint8_t *)&val , 8);

	while(i<20){
		tmp = val%(10);
		val = val/10;
		valArr[i] = tmp + '0';
        i++;
		
	}
	i = 0;
	while(valArr[20 - 1 - i] == '0' && i < 20){
		i++;
	}
	valArrLen = 20 - i;
	memcpy(qrBuffer , valArr , valArrLen);
	qrLength = valArrLen;
	Mem_Reverse(qrBuffer, qrLength);
}
#endif 

static void Qr_Response(Token_T* token){
	unsigned char ch = envData.channelEnable;
	
	QrWG_Send(token->data, token->length);
	if(ch & ENV_CH_KB){
		QrHidKeyboard_Report(token->data, token->length);
	}
#if 0
	if(envData.qrWorkMode == ENV_Qr_WorkMode_HNEncrypt){
		HNQR_Change();
	}
#endif 
	if(ch & ENV_CH_485P){
		if(!Command_Idle(0x01)){
			Command_Token_Set(TK_Slot_Qr, token);
		}
	}
}
static void QrHidKeyboard_Report(uint8_t buf[], uint32_t len);

static void Reader_Qr_Out(Token_T* token){
	uint8_t ch = envData.channelEnable;
	if(envData.qrWorkMode == ENV_Qr_WorkMode_HNEncrypt){
	//华诺加密模式
		if(ch & ENV_CH_KB){
			if(DecCharToValue(token->data[0]) > 9){
				HIDKeyboard_Report(0, REP_FRM_RAW, token->data, token->length);
			}
			else{
				if(envData.qrReverse){
					uint64_t val;
					uint8_t len = token->length;
					if(len > 18){
						len = 18;
					}
					DecStrToValue(token->data, len, &val);
					QrHidKeyboard_Report((uint8_t*)&val, 4);
				}
				else{
					HIDKeyboard_Report(0, REP_FRM_RAW, token->data, token->length);
				}
			}
		}
		if(ch & ENV_CH_485P){
			if(!Command_Idle(0x01)){
				Command_Token_Set(TK_Slot_Qr, token);
			}
		}
		
		QrWG_Send(token->data, token->length);
	}
	else{
		if(envData.qrWorkMode == 0){
			//透传模式
			if(envData.channelEnable & ENV_CH_485A){
				Command_CharRawSend(CH_UART, token->data, token->length);
			}
		}
		
		Qr_Response(token);
	}
}
static int Reader_Qr_Service(void){
	static uint8_t qbuf[300];
	uint8_t qlen = 0;
	if(Command_Token_Check(TK_Slot_Qr)){
		return 1;
	}
	Token_T * token = (Token_T *)qbuf;
	int r = Reader_QR_Read(token->data, &qlen);
	if(r == QR_S_NONE){
		return r;
	}
	if(r == QR_S_SUCCESS){
		token->length = qlen;
		token->type = TK_QR;
		Reader_Qr_Out(token);
		DeviceLight_Flash(1, Color_Green, 200);
		Buzzer_AsyncBeep(200);
	}
	else
	if(r == QR_S_CFG_OK){
		Reader_Warnning(2);
	}
	else{
		Reader_Warnning(3);
	}
	
	return r;
}

static int Reader_BLE_Service(void){
	if(!Command_Idle(0x03)){
		return 1;
	}
	CSN.nlen = 0;
	uint8_t bleLen = 0;
	int ret = Reader_BLE_Read(CSN.num, &bleLen);
	if(ret == BLE_ERR_NONE){
		return ret;
	}
	if(ret == BLE_ERR_OK){
		DeviceLight_Flash(1, Color_Green, 200);
		Buzzer_AsyncBeep(200);
		CSN.nlen = bleLen;
		CSN.type = 0;
		CSN.info = 0;
		CSN.ilen = 0;
		OutPut_CSN(&CSN);
		if(envData.channelEnable & ENV_CH_485A){
			Command_SyncSend(&CSN);
		}
	}
	else{
		Reader_Warnning(3);
	}
	
	return ret;
}
void TestRTC(void);
/*
开门
*/




static void MainTask(void *param) {
  int ret;
  Timer_Init();
  BSP_Init();
//	  const char* qr = "https://jdme.jd.com/jmeMobile/commonFun/visitingCard?user={\"userCode\":\"00528102\",\"userName\":\"changzhiguo1\",\"expirationTime\":\"1668060699495\",\"cardNo\":\"971019019\"}&timestamp=1668060639495&encry=dccb1810a56e8b11003227f8e087cc6a9a5f6c&to=visitingCard";
//		Reader_Qr_ReadCardNo((char*)qr, (uint32_t*)CSN.ibuf);

  Env_Init();
  Driver_Init();
  Init();
  ID_Init();
  USB_HID_Init();
  DeviceLight_Init();
  BSP_Sleep_Ms(500);
  StartUp();
  DBG_WRITE("Start\r\n");
//	  Test();
//	  CH455_Test();

#ifdef NDEBUG
  WatchDog_Start(2500);
#endif
  while (1) {
#ifdef NDEBUG
    WatchDog_Reset();
#endif
	if(rebootFlag){
		rebootFlag = 0;
		BSP_Sleep_Ms(100);
		BSP_ResetSystem();
	}

	if( xSemaphoreTake( mainSemaphore, 5 ) == pdTRUE ){
		Command_Process();
	}
	
    Env_Service();
	Timer_Service();
	
#if 1
	if(SignalService_Serve()){
		if(SignalService_IsTamp()){
			//拆机上报
			TampReport();
		}
		
		continue;
	}
#endif 
	
    if (readerReady) {
      readerReady = 0;
	  
	  if(Command_Idle(0x03)){
	      ret = Reader_CSN_Service(&CSN);
	      if (!ret) {
		  	input_event_t e;
		  	controller_input_event(input_event_build(&e, EV_T_Card, CSN.num, CSN.nlen));
#if 0
			DeviceLight_Flash(1, Color_Green, 200);
	        Buzzer_AsyncBeep(200);
//			  	Command_Rs485Out(&CSN);
	        OutPut_CSN(&CSN);
			if(envData.channelEnable & ENV_CH_485A){
				Command_SyncSend(&CSN);
			}

//				DKCommand_ReportCSN(&CSN);
	      } else {
		  	if(ret == 2){
//					DKCommand_ReportNAK();
			}
			else{
		        Reader_Error(ret);
			}
#endif 
	      }
	  }
	  
	  if(++readCount > 100){
	  	readCount = 0;
		WCI_Init();
	  }
    }

	Reader_Qr_Service();
	Reader_BLE_Service();
	if(rtcCount == 0){
		rtcCount = 600;
		SoftRTC_Sync();
	}
	KeyboardTask();
	controller_service();
  }
}

